#!usr/bin/env python
import random
import string
import math

class Jugador(object):
		def __init__(self,nombre,descripcion,autor):
			"""Inicializa al jugador"""
			self.nombre=nombre
			self.descripcion=descripcion
			self.criaturas=[]
			self.autor=autor
			self.puntaje=0
		
		def criaturas_restantes(self):
			"""Devuelve la cantidad de criaturas que un jugador posee en ese momento"""
			return len(self.criaturas)
			
		def devolver_autor(self):
			"""Devuelve el autor de un jugador"""
			return self.autor
		
		def devolver_nombre(self):
			"""Devuelve el nombre de un jugador"""
			return str(self.nombre)
			
		def agregar_criatura(self,criatura):
			"""Agrega una criatura a la lista de criaturas del jugador"""
			self.criaturas.append(criatura)
			
		def eliminar_criatura(self,criatura):
			"""Elimina una criatura de la lista de criaturas del jugador"""
			self.criaturas.remove(criatura)
			
		def elegir_criatura(self):
			"""Le permite al jugador elegir una criatura en base a su nombre. Si el jugador es una AI, se elige de forma aleatoria"""
			if len(self.criaturas)==0:
				return None
			if str.upper(self.autor)!="AI":
				while True:
					print ""
					print "()"+self.nombre+"()"+" usted cuenta con las siguientes criaturas:"
					for criatura in self.criaturas:
						print criatura.devolver_nombre()
					nombre=raw_input("Ingrese la criatura con la que desea combatir: ")
					for x in xrange(len(self.criaturas)):
						if nombre==self.criaturas[x].devolver_nombre():
							return self.criaturas[x]
					print "-#-Ingrese el nombre de una criatura que usted posea (case sensitive)-#-"
			else:
				return self.criaturas[random.randrange(0,len(self.criaturas),1)]
					
		def incrementar_puntaje(self):
			"""Incrementa en 10 el puntaje del jugador"""
			self.puntaje+=10
		
		def devolver_puntaje(self):
			"""Devuelve el puntaje del jugador"""
			return self.puntaje
				
		def elegir_accion(self,origen,destino):
			"""Le permite a un jugador elegir una determinada accion en base al nombre de la misma
			si la criatura cuenta con los requisitos para realizarla. Si el jugador es AI, hay dos variantes
			en la manera de elegir una accion."""
			diccionario_habilidades=origen.obtener_habilidades()
			origen_estado=origen.obtener_estado()
			if str.upper(self.autor)!="AI":
				imprimir_estados(origen.devolver_nombre(),str(origen.obtener_estado()),str(destino.obtener_estado()))
				for habilidad,descripcion in diccionario_habilidades.items():
					print str(habilidad)+": "+descripcion.devolver_descripcion()
				while True:
					accion=raw_input("Que ataque desea usar? ")
					if diccionario_habilidades.has_key(accion):
						if diccionario_habilidades[accion].obtener_costos()["mp"]<=origen_estado["mp"] and diccionario_habilidades[accion].obtener_costos()["hp"]<=origen_estado["hp"]:
							break
					print "Ingrese una habilidad valida acorde a sus estados y a las habilidades que tiene disponible (case sensitive)."
			else:
				#Intel Core i7 w/ HyperThreading
				accion=inteligencia_artificial(origen, destino)		
			return accion, destino

class JugadorAI(Jugador):
	def __init__(self):
		Jugador.__init__(self, "Bebiglia-Stankus", "Inteligencia artificial","AI")

def puede_usar_accion(habilidad, origen, origen_estado):
	"""Devuelve True si una criatura puede utilizar una determinada accion en base
	a su estado y False si no la puede utilizar"""
	return ((habilidad.obtener_costos().get("mp",0)<=origen_estado["mp"]) and (habilidad.obtener_costos().get("hp",0)<=origen_estado["hp"]))
	
def inteligencia_artificial(origen, destino):
	"""Recibe una criatura origen y una criatura destino sobre las cuales evaluara
	el mejor ataque que puede realizar"""
	diccionario_habilidades=origen.obtener_habilidades()
	origen_estado=origen.obtener_estado()
	hp_destino=destino.obtener_estado()["hp"]
	accion=None
	for clave,habilidad in diccionario_habilidades.items():
		lo_que_saca=habilidad.obtener_consecuencias(origen, destino)[1].get("hp", 0)
		if (hp_destino+lo_que_saca)<=0 and puede_usar_accion(habilidad, origen, origen_estado):
			accion=clave
			break
	if not accion:
		if origen_estado["hp"]<(origen.obtener_max()["hp"])/4:
			regen_aux=0
			accion_aux=None
			for clave,habilidad in diccionario_habilidades.items():
				regeneracion=habilidad.obtener_consecuencias(origen, destino)[0].get("hp",0)
				if regeneracion>regen_aux and puede_usar_accion(habilidad, origen, origen_estado):
					accion_aux=clave
					regen_aux=regeneracion
			accion=accion_aux
	if not accion:
		accion_aux=None
		lo_que_saca_aux=0
		for clave,habilidad in diccionario_habilidades.items():
			lo_que_saca=habilidad.obtener_consecuencias(origen, destino)[1].get("hp",0)
			if (abs(lo_que_saca)>abs(lo_que_saca_aux)) and puede_usar_accion(habilidad, origen, origen_estado):
				lo_que_saca_aux=lo_que_saca
				accion_aux=clave
		accion=accion_aux
	return accion
